
package com.nvlled.route;

import java.util.*;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;


public class Multimap<K, V> {

    // TODO: Change Deque to Map as the type of value
    private Map<K, Deque<V>> map;

    public Multimap() {
        map = new ConcurrentHashMap<K, Deque<V>>();
    }

    public Deque<V> getValues(K key) {
        Deque<V> values = map.get(key);
        if(values == null) {
            values = new ConcurrentLinkedDeque<V>();
            map.put(key, values);
        }

        // returning an encapsulated mutable object seems self-defeating
        // FIX: ?
        return values;
    }

    public void clear() {
       map.clear();
    }

    public int size() {
        return map.size();
    }

    public void add(K key, V val) {
        Deque<V> values = getValues(key);
        values.add(val);
    }

    public boolean hasKey(K key) {
        Collection<V> values = getValues(key);
        return !values.isEmpty();
    }

    public V remove(K key, V val) {
        Deque<V> values = getValues(key);
        if(values.remove(val)) {
            return val;
        }
        return null;
    }

    public List<K> keys() {
        List<K> ks = new ArrayList<K>();
        for(K key: map.keySet()) {
            if(hasKey(key)) {
                ks.add(key);
            }
        }
        return ks;
    }

    public Deque<V> removeAll(K key) {
        return map.remove(key);
    }
}

